from django.core.urlresolvers import reverse
from django.http import *
from django.shortcuts import *
from django import forms
from django.template import RequestContext 
from django.utils.translation import gettext
from django.utils.simplejson import *
from ytbase.helper import *
from ytcommunity.shorturl.model import *
from ytcommunity.shorturl.helper.context import *
import hashlib
import base64

class ShortURLForm(forms.Form):
    url = forms.URLField(max_length=250, initial='http://')

def add(request, template):
    if request.method == 'POST':
        form = ShortURLForm(request.POST)
        if form.is_valid():
            post = build_entry(form.cleaned_data['url'])
            redirect = get_url(post)            
            return HttpResponseRedirect(redirect)
    else:
        form = ShortURLForm() # An unbound form

    context = {'form': form}
    rc = RequestContext(request, processors=PROCESSORS)
    return render_to_response(template, context, rc)

def add_api(request):
    if request.method == 'POST':
        form = ShortURLForm(request.POST)
        if form.is_valid():
            post = build_entry(form.cleaned_data['url'])
            output = {"url": request.host_url + get_real_url(post)}
            json = dumps(output)
            return HttpResponse(json, mimetype="application/json")
    return HttpResponseNotFound()
    
@check_id_or_name(YTShortURL)
def display(request, id_or_name, template):
    post = get_by_str_id_or_name(YTShortURL, id_or_name)
    form = ShortURLForm() # An unbound form
            
    context = {
        'form':form,
        'post':post,
    }
    rc = RequestContext(request, processors=PROCESSORS)
    return render_to_response(template, context, rc)

@check_id_or_name(YTShortURL)
def redirect(request, id_or_name):
    post = get_by_str_id_or_name(YTShortURL, id_or_name)
    return HttpResponseRedirect(''.join(post.url))

def list(request, template):
    posts = YTShortURL.all().order('-update').fetch(20)
    context = {
        'posts':posts,
    }
    rc = RequestContext(request, processors=PROCESSORS)
    return render_to_response(template, context, rc)

def get_url(post):
    return reverse('ytcommunity.shorturl.view.url.display', 
                   kwargs={'id_or_name':str(post.key().id_or_name())})

def get_real_url(post):
    return reverse('ytcommunity.shorturl.view.url.redirect', 
                   kwargs={'id_or_name':str(post.key().id_or_name())})

def build_entry(url):
    post = YTShortURL.all().filter('url =', url).get()
    if post:
        post.points = post.points or 1
    else:
        post = find_key(url) or YTShortURL()
        post.url.append(url)

    post.points += 1
    post.put()
    return post

def find_key(url):
    m = hashlib.md5()
    m.update(url)
    encoded = base64.urlsafe_b64encode(m.digest())
    
    try:
        return find_key_base64(encoded)
    except:
        return None
    
def find_key_base64(str):
    if len(str) < 8:
        return None
    
    obj = find_url_obj(str[0:4])
    if obj:
        return obj

    obj = find_url_obj(str[0:5])
    if obj:
        return obj
    
    obj = find_url_obj(str[0:6])
    if obj:
        return obj
        
    return find_key_base64(str[1:])

def find_url_obj(key):
    if check_valid_key_name(key):
        obj = YTShortURL.get_or_insert(key)
        if not obj.url:
            return obj
    return None
